﻿using System;
using System.ComponentModel;
using System.Data;
using System.Data.Common;
using System.Data.SqlClient;
using Oracle.DataAccess.Client;

namespace DataService
{
    public static class DataObjectAdapter
    {
        public static DbConnection GetDbConnection(string pConnectionString, string pDefaultDB = "")
        {
            if (DataServiceUtil.DatabaseType() == DatabaseTypes.MS_SQL)
            {
                pConnectionString = string.Format("{0} ;Initial Catalog = {1}", pConnectionString, pDefaultDB);
                return new SqlConnection(pConnectionString);
            }
            else if (DataServiceUtil.DatabaseType() == DatabaseTypes.ORACLE)
            {
                return new OracleConnection(pConnectionString);
            }
            else
            {
                throw new ApplicationException(DataServiceUtil.UnknownDbType);
            }
        }

        public static DbCommand GetCommand()
        {
            if (DataServiceUtil.DatabaseType() == DatabaseTypes.MS_SQL)
            {
                return new SqlCommand();
            }
            else if (DataServiceUtil.DatabaseType() == DatabaseTypes.ORACLE)
            {
                return new OracleCommand();
            }
            else
            {
                throw new ApplicationException(DataServiceUtil.UnknownDbType);
            }
        }

        public static DbCommand GetCommand(string pCommantText)
        {
            if (DataServiceUtil.DatabaseType() == DatabaseTypes.MS_SQL)
            {
                return new SqlCommand(pCommantText);
            }
            else if (DataServiceUtil.DatabaseType() == DatabaseTypes.ORACLE)
            {
                return new OracleCommand(pCommantText);
            }
            else
            {
                throw new ApplicationException(DataServiceUtil.UnknownDbType);
            }
        }

        public static DbCommand GetCommand(string pCommantText, DbConnection pConnection)
        {
            if (DataServiceUtil.DatabaseType() == DatabaseTypes.MS_SQL)
            {
                return new SqlCommand(pCommantText, (SqlConnection)pConnection);
            }
            else if (DataServiceUtil.DatabaseType() == DatabaseTypes.ORACLE)
            {
                return new OracleCommand(pCommantText, (OracleConnection)pConnection);
            }
            else
            {
                throw new ApplicationException(DataServiceUtil.UnknownDbType);
            }
        }

        public static DbDataAdapter GetDataAdapter()
        {
            if (DataServiceUtil.DatabaseType() == DatabaseTypes.MS_SQL)
            {
                return new SqlDataAdapter();
            }
            else if (DataServiceUtil.DatabaseType() == DatabaseTypes.ORACLE)
            {
                return new OracleDataAdapter();
            }
            else
            {
                throw new ApplicationException(DataServiceUtil.UnknownDbType);
            }
        }

        public static DbDataAdapter GetDataAdapter(DbCommand pDbCommand)
        {
            if (DataServiceUtil.DatabaseType() == DatabaseTypes.MS_SQL)
            {
                return new SqlDataAdapter((SqlCommand)pDbCommand);
            }
            else if (DataServiceUtil.DatabaseType() == DatabaseTypes.ORACLE)
            {
                return new OracleDataAdapter((OracleCommand)pDbCommand);
            }
            else
            {
                throw new ApplicationException(DataServiceUtil.UnknownDbType);
            }
        }

        public static DbCommandBuilder GetCommandBuilder(DbDataAdapter pDataAdapter)
        {
            if (DataServiceUtil.DatabaseType() == DatabaseTypes.MS_SQL)
            {
                return new SqlCommandBuilder((SqlDataAdapter)pDataAdapter);
            }
            else if (DataServiceUtil.DatabaseType() == DatabaseTypes.ORACLE)
            {
                return new OracleCommandBuilder((OracleDataAdapter)pDataAdapter);
            }
            else
            {
                throw new ApplicationException(DataServiceUtil.UnknownDbType);
            }
        }

        public static DbParameter GetParameter(string pClmnNamePrefix, DataColumn pDc)
        {
            string parameterName = string.Join("", pClmnNamePrefix, pDc.ColumnName);
            int size = 0;
            ParameterDirection prmDirection = ParameterDirection.Input;
            byte precision = 0;
            byte scale = 0;
            string srcColumn = pDc.ColumnName;
            DataRowVersion dataRowVersion = DataRowVersion.Current;

            object value = null;

            if (DataServiceUtil.DatabaseType() == DatabaseTypes.MS_SQL)
            {
                bool srcClmnNullMapping = false;
                return new SqlParameter(parameterName, GetSqlDBType(pDc.DataType), size, prmDirection, precision, scale, srcColumn, dataRowVersion, srcClmnNullMapping, value, string.Empty, string.Empty, string.Empty);
            }
            else if (DataServiceUtil.DatabaseType() == DatabaseTypes.ORACLE)
            {
                bool isNulable = false;
                return new OracleParameter(parameterName, GetOracleDBType(pDc.DataType), size, prmDirection, isNulable, precision, scale, srcColumn, dataRowVersion, value);
            }
            else
            {
                throw new ApplicationException(DataServiceUtil.UnknownDbType);
            }
        }

        private static SqlDbType GetSqlDBType(Type pType)
        {
            SqlParameter prm = new SqlParameter();

            TypeConverter tc = TypeDescriptor.GetConverter(prm.DbType);
            if (tc.CanConvertFrom(pType))
                prm.DbType = (DbType)tc.ConvertFrom(pType.Name);
            else
            {
                try
                {
                    prm.DbType = (DbType)tc.ConvertFrom(pType.Name);
                }
                catch
                {
                    //Do Nothing
                }
            }
            return prm.SqlDbType;
        }

        private static OracleDbType GetOracleDBType(Type pType)
        {
            OracleParameter prm = new OracleParameter();

            TypeConverter tc = TypeDescriptor.GetConverter(prm.DbType);
            if (tc.CanConvertFrom(pType))
                prm.DbType = (DbType)tc.ConvertFrom(pType.Name);
            else
            {
                try
                {
                    prm.DbType = (DbType)tc.ConvertFrom(pType.Name);
                }
                catch
                {
                    //Do Nothing
                }
            }
            return prm.OracleDbType;
        }
    }
}
